import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/animation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:pytorch_lite/pytorch_lite.dart';


import 'gobal.dart';
import 'imagecropexample.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      navigatorKey: Global.navigatorKey,
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // TRY THIS: Try running your application with "flutter run". You'll see
        // the application has a purple toolbar. Then, without quitting the app,
        // try changing the seedColor in the colorScheme below to Colors.green
        // and then invoke "hot reload" (save your changes or press the "hot
        // reload" button in a Flutter-supported IDE, or press "r" if you used
        // the command line to start the app).
        //
        // Notice that the counter didn't reset back to zero; the application
        // state is not lost during the reload. To reset the state, use hot
        // restart instead.
        //
        // This works for code too, not just values: Most code changes can be
        // tested with just a hot reload.
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

Future<Uint8List> _getImageBytes(String path) async {
  final byteData = await rootBundle.load(path);
  return byteData.buffer.asUint8List();
}

class _MyHomePageState extends State<MyHomePage> {
  static String defaultImageString = "assets/test1.jpg";

  ///痘痘的人脸图
  var imageOBS = Image.asset(defaultImageString).obs;

  FileImage? fileImage;

  ///痘痘的框框数组
  var squarePositionList = [].obs;

  ///Listview选中的痘痘 带动画特效  AnimatedPositioned 先隐藏起来 ,Rx<AnimatedPositioned>类型老是报错
  AnimatedPositioned animatedPositioned = AnimatedPositioned(
    left: 0,
    top: 0,
    width: 0,
    height: 0,
    duration: Duration(milliseconds: 300),
    child: Container(),
  );

  ///listview 列表的数据源
  List<ResultObjectDetection> objDetectionList = [];

  ///listview 列表选中的痘痘模型
  late ResultObjectDetection selectedObjectDetection;

  ///控制痘痘的框框的 粗细控制系数
  int widthAdjustmentFactor = 800;

  Future<void> addImageTest() async {
    final ImagePicker picker = ImagePicker();
    XFile? xfile = await picker.pickImage(source: ImageSource.gallery);
    if(xfile != null) {
      // imageOBS.value = Image.asset(xfile!.path);
      setState(() {
        imageOBS.value = Image.file(File(xfile!.path));
      });
    }
  }

  Future<void> addRedSquareToDefaultImage() async {
    imageOBS.value = Image.asset(defaultImageString);
    Uint8List uint8list = await _getImageBytes(defaultImageString);
    final ImageStream stream = imageOBS.value.image.resolve(ImageConfiguration.empty);
    stream.addListener(
        ImageStreamListener((ImageInfo info, bool synchronousCall) async {
          final myImage = info.image;
          final Size size =
          Size(myImage.width.toDouble(), myImage.height.toDouble());
          ModelObjectDetection objectModel =
          await PytorchLite.loadObjectDetectionModel("assets/last.torchscript",
              2, size.width.toInt(), size.height.toInt(),
              labelPath: "assets/label.txt",
              objectDetectionModelType: ObjectDetectionModelType.yolov8);

          List<ResultObjectDetection> objDetect =
          await objectModel.getImagePrediction(uint8list,
              minimumScore: 0.01, iOUThreshold: 0.1, boxesLimit: 10);
          objDetectionList = objDetect;
          int screenWidth = MediaQuery.of(context).size.width.toInt();
          squarePositionList.value = [];
          for (ResultObjectDetection res in objDetect) {
            double top = res.rect.top;
            double left = res.rect.left;
            double bottom = res.rect.bottom;
            double right = res.rect.right;
            double width = res.rect.width;
            double height = res.rect.height;
            double topPosition = top * screenWidth;
            double leftPosition = left * screenWidth;
            double bottomPosition = bottom * screenWidth;
            double rightPosition = right * screenWidth;
            double widthPosition = width * screenWidth;
            double heightPosition = height * screenWidth;

            ///控制红框的宽度
            double widthAdjustment = width * height * widthAdjustmentFactor;

            Positioned positioned = Positioned(
                top: topPosition,
                left: leftPosition,
                width: widthPosition,
                height: heightPosition,
                child: Container(
                  decoration: BoxDecoration(
                      border:
                      Border.all(color: Colors.pink, width: widthAdjustment)),
                ));
            squarePositionList.add(positioned);
          }
        }));
  }



  Future<void> getImageFromGalleryToDetect() async {
    final ImagePicker picker = ImagePicker();
    XFile? xfile = await picker.pickImage(source: ImageSource.gallery);
    if(xfile != null){
      imageOBS.value = Image.file(File(xfile.path));
      Uint8List uint8list = await File(xfile.path).readAsBytes();
      // Uint8List uint8list = await _getImageBytes(xfile.path);
      final ImageStream stream = imageOBS.value.image.resolve(ImageConfiguration.empty);
      stream.addListener(
          ImageStreamListener((ImageInfo info, bool synchronousCall) async {
            final myImage = info.image;
            final Size size =
            Size(myImage.width.toDouble(), myImage.height.toDouble());
            ModelObjectDetection objectModel =
            await PytorchLite.loadObjectDetectionModel("assets/last.torchscript",
                2, size.width.toInt(), size.height.toInt(),
                labelPath: "assets/label.txt",
                objectDetectionModelType: ObjectDetectionModelType.yolov8);

            List<ResultObjectDetection> objDetect =
            await objectModel.getImagePrediction(uint8list,
                minimumScore: 0.01, iOUThreshold: 0.1, boxesLimit: 10);
            objDetectionList = objDetect;
            int screenWidth = MediaQuery.of(context).size.width.toInt();
            squarePositionList.value = [];
            for (ResultObjectDetection res in objDetect) {
              double top = res.rect.top;
              double left = res.rect.left;
              double bottom = res.rect.bottom;
              double right = res.rect.right;
              double width = res.rect.width;
              double height = res.rect.height;
              double topPosition = top * screenWidth;
              double leftPosition = left * screenWidth;
              double bottomPosition = bottom * screenWidth;
              double rightPosition = right * screenWidth;
              double widthPosition = width * screenWidth;
              double heightPosition = height * screenWidth;

              ///控制红框的宽度
              double widthAdjustment = width * height * widthAdjustmentFactor;

              Positioned positioned = Positioned(
                  top: topPosition,
                  left: leftPosition,
                  width: widthPosition,
                  height: heightPosition,
                  child: Container(
                    decoration: BoxDecoration(
                        border:
                        Border.all(color: Colors.pink, width: widthAdjustment)),
                  ));
              squarePositionList.add(positioned);
            }
          }));
    }
  }


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    addRedSquareToDefaultImage();
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // TRY THIS: Try changing the color here to a specific color (to
        // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        // change color while the other colors stay the same.
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: GestureDetector(
            onTap: () {

            },
            child: Text(widget.title)),
      ),
      body: Obx(
        () => Column(
          // Center is a layout widget. It takes a single child and positions it
          // in the middle of the parent.
          children: [
            SizedBox(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.width,
              child: Stack(children: [
                Positioned.fill(child: imageOBS.value),
                ...squarePositionList,
                animatedPositioned
              ]),
            ),
            Expanded(
              child: ListView.builder(
                  itemBuilder: (BuildContext context, int index) {
                    selectedObjectDetection = objDetectionList[index];
                    int screenWidth =
                    MediaQuery.of(context).size.width.toInt();
                    double top = selectedObjectDetection.rect.top;
                    double left = selectedObjectDetection.rect.left;
                    double bottom = selectedObjectDetection.rect.bottom;
                    double right = selectedObjectDetection.rect.right;
                    double width = selectedObjectDetection.rect.width;
                    double height = selectedObjectDetection.rect.height;

                    double topPosition = top * screenWidth;
                    double leftPosition = left * screenWidth;
                    double bottomPosition = bottom * screenWidth;
                    double rightPosition = right * screenWidth;
                    double widthPosition = width * screenWidth;
                    double heightPosition = height * screenWidth;
                    double widthAdjustment =
                        width * height * widthAdjustmentFactor;
                    // 点击每一个具体识别结果的相应
                    return GestureDetector(
                      behavior: HitTestBehavior.opaque,
                      onTap: () {
                        print('_MyHomePageState.buildindex $index');



                        setState(() {
                          animatedPositioned = AnimatedPositioned(
                              curve: Curves.bounceInOut,
                              top: topPosition,
                              left: leftPosition,
                              width: widthPosition,
                              height: heightPosition,
                              duration: const Duration(milliseconds: 300),
                              child: Container(
                                decoration: BoxDecoration(
                                    border: Border.all(
                                        color: Colors.pink,
                                        width: widthAdjustment)),
                              ));
                        });

                        ///只显示一个痘痘 所以 要clear以下
                        squarePositionList.clear();
                      },
                      child: Column(
                        children: [
                          SizedBox(height: 20),
                          Container(
                            height: 50,
                            child:  Row(
                              mainAxisAlignment: MainAxisAlignment.start,
                              children: [
                                const SizedBox(width: 20),
                                // Obx((){
                                //   return imageOBS.value;
                                // }),
                                // ClipImage(imagePath: defaultImageString, startOffset: Offset(0,0), clipWidth: 50, clipHeight: 50,),
                                ClipImage(imagePath: defaultImageString, startOffset: Offset(left * 640,top * 640), clipWidth: width*640, clipHeight: height*640,),
                                const SizedBox(width: 10),
                                Text(
                                  "Accuracy:${(objDetectionList[index].score * 100).toStringAsFixed(0)}",
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    );
                  },
                  itemCount: objDetectionList.length),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: getImageFromGalleryToDetect,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}



